#include "stdafx.h"

#include <opencv2/legacy/legacy.hpp>
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/photo/photo.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/nonfree/features2d.hpp"
#include "opencv2/calib3d/calib3d.hpp"

#include "ImageMethods.h"
#include "RGBColour.h"

class ImageMethods;

using namespace cv;
using namespace std;

ImageMethods::ImageMethods(void)
{
}

ImageMethods::~ImageMethods(void)
{
}

// x is the abscissa
// y is the ordinate
unsigned char ImageMethods::getPixel(IplImage* image, int x, int y)
{
  return ((unsigned char*)(image->imageData + image->widthStep*y))[x*image->nChannels];
}

//gets pixel at image position (x,y)
RGBColour ImageMethods::getColourPixel(IplImage* image, int x, int y)
{
   RGBColour rgb;
   rgb.b = ((unsigned char*)(image->imageData + image->widthStep*y))[x*image->nChannels + 0];
   rgb.g = ((unsigned char*)(image->imageData + image->widthStep*y))[x*image->nChannels + 1];
   rgb.r = ((unsigned char*)(image->imageData + image->widthStep*y))[x*image->nChannels + 2];
   return rgb;
}

//sets pixel at image position (x,y)
// x is the abscissa
// y is the ordinate
// value is the new pixel value
void ImageMethods::setPixel(IplImage* image, int x, int y, unsigned char value)
{
  ((unsigned char*)(image->imageData + image->widthStep*y))[x*image->nChannels]=value;
}

//sets pixel at image position (x,y)
void ImageMethods::setColourPixel(IplImage* image, int x, int y, RGBColour& rgb)
{
   ((unsigned char*)(image->imageData + image->widthStep*y))[x*image->nChannels + 0] = rgb.b;
   ((unsigned char*)(image->imageData + image->widthStep*y))[x*image->nChannels + 1] = rgb.g;
   ((unsigned char*)(image->imageData + image->widthStep*y))[x*image->nChannels + 2] = rgb.r;
}

int ImageMethods::compareGreyImages(Mat img1, Mat img2)
{
	double imageDistance = 0;
	double incorrect = 0;
	IplImage* diffImage;
	IplImage* patchImage;
	IplImage* image1=cvCloneImage(&(IplImage)img1);
	IplImage* image2=cvCloneImage(&(IplImage)img2);

	diffImage = cvCreateImage(cvSize(image1->width,image1->height),IPL_DEPTH_8U,1); //create image
	patchImage = cvCreateImage(cvSize(image1->width,image1->height),IPL_DEPTH_8U,3); //create image

	for(int x = 0; x < image1->width; x++)
	{
		for(int y = 0; y < image1->height; y++)
		{

			unsigned char g1 = getPixel(image1,x,y);
			unsigned char g2 = getPixel(image2,x,y);
			RGBColour px1 = getColourPixel(image1,x,y);
			RGBColour px2 = getColourPixel(image2,x,y);

			if (g1 != g2)
			{
				incorrect++;		
				//draw white pixel
				RGBColour whitePix = RGBColour(255,255,255);
				RGBColour blackPix = RGBColour(0,0,0);
				RGBColour redPix = RGBColour(255,0,0);
				setPixel(diffImage,x,y,75);
				if(g1 == 0)
				{
					setColourPixel(patchImage,x,y,redPix);
				}
				if(g1 == 255)
				{
					setColourPixel(patchImage,x,y,blackPix);
				}
			}
			else
			{
				//draw black pixel
				RGBColour whitePix = RGBColour(255,255,255);
				RGBColour blackPix = RGBColour(0,0,0);
				setPixel(diffImage,x,y,g2);			
				if(g1 == 0)
				{
					setColourPixel(patchImage,x,y,blackPix);
				}
				if(g1 == 255)
				{
					setColourPixel(patchImage,x,y,whitePix);
				}
			}

			RGBColour* h1 = &RGBColour(0.0,0.0,0.0);
			RGBColour* h2 = &RGBColour(0.0,0.0,0.0);

		}
	}

	cvNamedWindow("Error Image", CV_WINDOW_AUTOSIZE);
	cvShowImage("Error Image", diffImage);
	cvNamedWindow("Patched Image", CV_WINDOW_AUTOSIZE);
	cvShowImage("Patched Image", patchImage);

	printf("Inorrect: %f \n",incorrect);
	printf("Total: %d \n",image1->width*image1->height);

	imageDistance = (incorrect/(image1->width*image1->height))*100;

	return imageDistance;
}

int ImageMethods::compareColourImages(Mat img1, Mat img2)
{
	double imageDistance = 0;
	double incorrect = 0;
	IplImage* diffImage;
	IplImage* patchImage;
	IplImage* image1=cvCloneImage(&(IplImage)img1);
	IplImage* image2=cvCloneImage(&(IplImage)img2);

	diffImage = cvCreateImage(cvSize(image1->width,image1->height),IPL_DEPTH_8U,1); //create image
	patchImage = cvCreateImage(cvSize(image1->width,image1->height),IPL_DEPTH_8U,3); //create image

	for(int x = 0; x < image1->width; x++)
	{
		for(int y = 0; y < image1->height; y++)
		{
			RGBColour px1 = getColourPixel(image1,x,y);
			RGBColour px2 = getColourPixel(image2,x,y);

			if (px1.r > (px2.r+(255/15)) || px1.r < (px2.r-(255/15)) || px1.g > (px2.g+(255/15)) || px1.g < (px2.g-(255/15)) || px1.b > (px2.b+(255/15)) || px1.b < (px2.b-(255/15)))
			{
				incorrect++;		
				//draw white pixel
				RGBColour whitePix = RGBColour(255,255,255);
				setPixel(image2,x,y,100);
				setColourPixel(patchImage,x,y,px1);
			}
			else
			{
				//draw black pixel
				RGBColour blackPix = RGBColour(0,0,0);
				setPixel(diffImage,x,y,0);			
				setColourPixel(patchImage,x,y,px2);
			}

			RGBColour* h1 = &RGBColour(0.0,0.0,0.0);
			RGBColour* h2 = &RGBColour(0.0,0.0,0.0);

		}
	}

	cvNamedWindow("Error Image", CV_WINDOW_AUTOSIZE);
	cvShowImage("Error Image", diffImage);
	cvNamedWindow("Patched Image", CV_WINDOW_AUTOSIZE);
	cvShowImage("Patched Image", patchImage);

	printf("Inorrect: %f \n",incorrect);
	printf("Total: %d \n",image1->width*image1->height);

	imageDistance = (incorrect/(image1->width*image1->height))*100;

	return imageDistance;
}

int ImageMethods::saveImage(IplImage* img1, String filename)
{
	/* Convert Mat to IplImage and save */
	//IplImage* image =cvCloneImage(&(IplImage)img1);
	const char* name = filename.c_str();
	//file = "test.png";
	cvSaveImage((filename+".png").c_str(), img1);
	return 0;
}
